/**
 * 
 */
package denaris.core;

import java.util.Enumeration;
import java.util.Vector;

import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.game.Sprite;

import denaris.core.controller.AbstractController;
import denaris.core.entity.AbstractEntity;
import denaris.core.listener.ICollisionListener;
import denaris.factory.ImageFactory;

/**
 * @author stkl23
 * 
 */
public abstract class BulletEmitter extends AbstractParticleEmitter {
	private Image bullets;

	private int bulletFrame;
	
	private int maxBulletFrames;

	private int bulletWidth;

	private int bulletHeight;

	private ICollisionListener collisionListener;

	public BulletEmitter(int cacheSize, int dx, int dy, String bulletImgPath, int bulletWidth, int bulletHeight) {
		super(cacheSize, dx, dy);
		// load the bullet-image
		bullets = ImageFactory.getImage(bulletImgPath);
		this.bulletWidth = bulletWidth;
		this.bulletHeight = bulletHeight;
		this.bulletFrame = 0;
	}

	protected AbstractParticle createNew() {
		// first we create the bullet sprite
		Sprite s = new Sprite(bullets, bulletWidth, bulletHeight);
		maxBulletFrames = s.getRawFrameCount();
		AbstractController controller = createController();
		controller.setSprite(s);
		// now we can create and return the Bullet
		return new Bullet(controller);
	}
	
	protected AbstractParticle next() {
		// set the current bullet frame... otherwise the cached elements are not updated
		AbstractParticle abstractParticle = super.next();
		if (abstractParticle != null) {
			abstractParticle.getController().getSprite().setFrame(bulletFrame);
		}
		return abstractParticle;
	}

	public int getBulletFrame() {
		return bulletFrame;
	}

	public void setBulletFrame(int bulletFrame) {
		this.bulletFrame = bulletFrame;
	}
	
	public void nextBulletFrame() {
		if (bulletFrame < maxBulletFrames - 1) {
			bulletFrame++;
		}
	}

	public abstract AbstractController createController();

	public void checkCollision(Vector entities) {
		Enumeration particles = elements();
		while (particles.hasMoreElements()) {
			AbstractParticle particle = (AbstractParticle) particles
					.nextElement();
			if (particle.isActive()) {
				Enumeration e = entities.elements();
				while (e.hasMoreElements()) {
					AbstractEntity entity = (AbstractEntity) e
					.nextElement();
					if (collidesWith(particle, entity)) {
						notifyCollision(particle, entity);
						break;
					}
				}
			}
		}
	}
	
	public void checkCollision(TiledMap map) {
		Enumeration particles = elements();
		while (particles.hasMoreElements()) {
			AbstractParticle particle = (AbstractParticle) particles.nextElement();
			if (particle.isActive() && collidesWith(particle, map)) {
				notifyCollision(particle, map);
			}
		}
	}

	protected void notifyCollision(AbstractParticle particle,
			AbstractEntity entity) {
		if (collisionListener != null) {
			collisionListener.onCollision(particle, entity);
		}
	}
	
	protected void notifyCollision(AbstractParticle particle, TiledMap map) {
		if (collisionListener != null) {
			collisionListener.onCollision(particle, map);
		}
	}
	
	public abstract boolean collidesWith(AbstractParticle particle,
			AbstractEntity entity);
	
	public abstract boolean collidesWith(AbstractParticle particle, TiledMap map);

	public ICollisionListener getCollisionListener() {
		return collisionListener;
	}

	public void setCollisionListener(ICollisionListener collisionListener) {
		this.collisionListener = collisionListener;
	}
}
